package com.aysafety.iotdataplatformweb.services.hydraulicsupport.impl;

import com.aysafety.core.DBDriver.hbase.HBaseDriver;
import com.aysafety.core.common.DateUtils;
import com.aysafety.iotdataplatformweb.common.PythonAlgorithmUtils;
import com.aysafety.iotdataplatformweb.dao.ComprehensiveWarningDao;
import com.aysafety.iotdataplatformweb.dao.HydraulicsupportDao;
import com.aysafety.iotdataplatformweb.dao.MicroseismDao;
import com.aysafety.iotdataplatformweb.dao.TreeDao;
import com.aysafety.iotdataplatformweb.services.hydraulicsupport.HydraulicSupportService;
import com.safety.algorithm.eigenvalue.EigenvalueAlgorithm;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;

@Service
public class HydraulicSupportServiceImpl implements HydraulicSupportService {

    private final int SIZE = 10000;

    private final Map<String, Object> warning = new HashMap<String, Object>() {
        {
            put("entId", "String");
            put("deviceId", "String");
            put("w1", "Double");
            put("fitness", "Double");
            put("datetime", "Date");
            put("last", "String");
        }
    };
    @Autowired
    HydraulicsupportDao hydraulicsupportDao;
    @Autowired
    PythonAlgorithmUtils pythonAlgorithmUtils;
    @Autowired
    TreeDao treeDao;
    @Autowired
    MicroseismDao microseismDao;
    @Autowired
    ComprehensiveWarningDao comprehensiveWarningDao;

    private static List<Map<String, Object>> removeDuplicateWithOrder(List<Map<String, Object>> list) {
        Set<Map<String, Object>> set = new HashSet();
        List<Map<String, Object>> newList = new ArrayList<Map<String, Object>>();
        for (int i = 0; i < list.size(); i++) {
            Map<String, Object> map = new HashMap<String, Object>(2);
            map.put("entId", list.get(i).get("entId"));
            map.put("workingFace", list.get(i).get("workingFace"));
            map.put("deviceId", list.get(i).get("deviceId"));
            if (set.add(map)) {
                newList.add(map);
            }
        }
        return newList;
    }

    @Override
    public long countByHydraulicSupport(String mineId, String deviceId, String startTime, String endTime, int timeSpan,
                                        String timeUnit) throws Throwable {
        long startTimeTimestamp = DateUtils.fomatDateTime(startTime).getTime();
        long endTimeTimestamp = DateUtils.fomatDateTime(endTime).getTime();
        Map<String, Object> parram = new HashMap<String, Object>();
        parram.put("tableId", mineId + "." + "HydraulicSupportRealTime");
        parram.put("entId", "\'" + mineId + "\'");
        parram.put("deviceId", "\'" + deviceId + "\'");
        parram.put("startTime", startTimeTimestamp);
        parram.put("endTime", endTimeTimestamp);
        return hydraulicsupportDao.countByHydraulicSupport(parram);
    }

    @Override
    public List<Map<String, Object>> queryRealTimeByHydraulicSupport(String mineId, String deviceId, String startTime,
                                                                     String endTime, int timeSpan, String timeUnit, int page, int size, String startRow) throws Throwable {
        long startTimeTimestamp = DateUtils.fomatDateTime(startTime).getTime();
        long endTimeTimestamp = DateUtils.fomatDateTime(endTime).getTime();
        Map<String, Object> parram = new HashMap<String, Object>();
        parram.put("tableId", mineId + "." + "HydraulicSupportRealTime");
        parram.put("entId", "\'" + mineId + "\'");
        parram.put("deviceId", "\'" + deviceId + "\'");
        parram.put("startTime", startTimeTimestamp);
        parram.put("endTime", endTimeTimestamp);
        //parram.put("size", size);

        List<Map<String, Object>> result = hydraulicsupportDao.queryRealTimeByHydraulicSupport(parram);
        for (int i = 0; i < result.size(); i++) {
            long timestamp = (long) result.get(i).get("datetime");
            Date dateTime = DateUtils.fomatDateTime(timestamp);
            result.get(i).put("datetime", DateUtils.getTime(dateTime));
        }
        return result;
    }

    @Override
    public List<Map<String, Object>> queryFrequency(String mineId, String deviceId, String startTime, String endTime,
                                                    int timeSpan, String timeUnit) throws Throwable {

        long startTimeTimestamp = DateUtils.fomatDateTime(startTime).getTime();
        long endTimeTimestamp = DateUtils.fomatDateTime(endTime).getTime();
        Map<String, Object> parram = new HashMap<String, Object>();
        parram.put("tableId", mineId + "." + "CALHYFREQUENCY");
        parram.put("entId", "\'" + mineId + "\'");
        parram.put("deviceId", "\'" + deviceId + "\'");
        parram.put("startTime", startTimeTimestamp);
        parram.put("endTime", endTimeTimestamp);

        List<Map<String, Object>> result = hydraulicsupportDao.queryFrequency(parram);
        for (int i = 0; i < result.size(); i++) {
            long timestamp = (long) result.get(i).get("datetime");
            Date dateTime = DateUtils.fomatDateTime(timestamp);
            result.get(i).put("datetime", DateUtils.getTime(dateTime));
        }
        return result;
    }

    @Override
    public List<Map<String, Object>> queryFlicker(String mineId, String deviceId, String startTime, String endTime,
                                                  int timeSpan, String timeUnit) throws Throwable {

        //Map<String, Map<String, Object>> results = new HashMap<>();
        long start = DateUtils.fomatDateTime(startTime).getTime();
        long end = DateUtils.fomatDateTime(endTime).getTime();
        Map<String, Object> params = new HashMap<>();
        params.put("tableId", mineId + "." + "FlickerIntervalRisk");
        params.put("startTime", start);
        params.put("endTime", end);
        params.put("deviceId", "\'" + deviceId + "\'");

        Map<String, Object> datetimeAndI = new HashMap<>();
        List<Map<String, Object>> result = hydraulicsupportDao.queryFlicker(params);
        for (int i = 0; i < result.size(); i++) {
            long timestamp = (long) result.get(i).get("datetime");
            Date dateTime = DateUtils.fomatDateTime(timestamp);
            result.get(i).put("datetime", DateUtils.getTime(dateTime));
        }
        /*for (Map<String, Object> map : resultsList) {
            datetimeAndI.putAll(map);
        }
        results.put(deviceId, datetimeAndI);*/
        return result;
    }


    /*public List<Map<String, Object>> queryFlicker(String mineId, String deviceId, String startTime, String endTime,
        int timeSpan, String timeUnit) throws Throwable {
        *//**
     *  计算闪烁时间间隔危险程度I
     *  公式：I=1/(t_2-t_1 )
     *  t_1表示前一次闪烁的时间，t_2表示后一次闪烁的时间
     *  1.查询数据
     *  2.  flag > avg:2 ; avg/10 <  flag <= avg :1 ; flag < avg/10 : 0
     *      2    0     2  即为一次闪烁
     *      a.向前找到2
     *      b.在2找到0
     *      c.接着再找到一个2
     * *//*

     *//********************1.查询数据***********************//*
        long startTimeTimestamp = DateUtils.fomatDateTime(startTime).getTime();
        long endTimeTimestamp = DateUtils.fomatDateTime(endTime).getTime();
        Map<String, Object> parram = new HashMap<String, Object>();
        parram.put("tableId", mineId + "." + "CalHyFlicker");
        parram.put("entId", "\'" + mineId + "\'");
        parram.put("deviceId", "\'" + deviceId + "\'");
        parram.put("startTime", startTimeTimestamp);
        parram.put("endTime", endTimeTimestamp);

        List<Map<String, Object>> datas = hydraulicsupportDao.queryFlicker(parram);
        *//*for (int i = 0; i < datas.size(); i++) {
            long timestamp = (long) datas.get(i).get("datetime");
            Date dateTime = DateUtils.fomatDateTime(timestamp);
            datas.get(i).put("datetime", DateUtils.getTime(dateTime));
        }*//*
        long t_1 = 0;
        long t_2 = 0;
        double I = 0;
        List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();

        loop:for (int i = 0; i < datas.size(); i++) {

            Map<String, Object> map = datas.get(i);
            long datetime = (long) map.get("datetime");
            double leftFlag = (double) map.get("leftFlag");
            double rightFlag = (double) map.get("rightFlag");
            double totalFlag = (double) map.get("totalFlag");

            *//********************************计算前一次闪烁时间 2<--0<--2 ********************************//*
            //向前查询flag为2的数据
            parram.put("endTime", datetime);
            parram.put("leftFlag", 2);
            parram.put("size", 1);
            //topList1：临近的一次高于avg的点
            List<Map<String, Object>> topList1 = hydraulicsupportDao.queryFlicker(parram);
            if (topList1.size() > 0) {
                long topTime1 = (long) topList1.get(0).get("datetime");
                //向前找到低于avg/10的点
                parram.put("endTime", topTime1);
                parram.put("leftFlag", 0);
                parram.put("size", 1);
                List<Map<String, Object>> bottomList = hydraulicsupportDao.queryFlicker(parram);
                if (bottomList.size() > 0) {
                    //出现低于avg/10，则向前继续查询高于avg的数据
                    //向前查询flag为2的数据
                    long bottomTime = (long) bottomList.get(0).get("datetime");
                    parram.put("endTime", bottomTime);
                    parram.put("leftFlag", 2);
                    parram.put("size", 1);
                    //topList--代表高于avg
                    List<Map<String, Object>> topList2 = hydraulicsupportDao.queryFlicker(parram);
                    if (topList2.size() > 0) {
                        //记录为一次闪烁
                        t_1 = (long) topList2.get(0).get("datetime");
                    }
                }
                */

    /********************************计算前后一次闪烁时间 2-->0--->2 ********************************//*
                //向后查询flag为2的数据
                parram.remove("endTime");
                parram.put("startTime", datetime);
                parram.put("leftFlag", 2);
                parram.put("size", 1);
                List<Map<String, Object>> topList3 = hydraulicsupportDao.queryFlicker(parram);
                if (topList3.size() > 0) {
                    long topTime3 = (long) topList3.get(0).get("datetime");
                    //向后找到低于avg/10的点
                    parram.put("startTime", topTime3);
                    parram.put("leftFlag", 0);
                    parram.put("size", 1);
                    List<Map<String, Object>> bottomList1 = hydraulicsupportDao.queryFlicker(parram);
                    if (bottomList1.size() > 0) {
                        //出现低于avg/10，则向后继续查询高于avg的数据
                        //向后查询flag为2的数据
                        long bottomTime1 = (long) bottomList1.get(0).get("datetime");
                        parram.put("startTime", bottomTime1);
                        parram.put("leftFlag", 2);
                        parram.put("size", 1);
                        //topList--代表高于avg
                        List<Map<String, Object>> topList4 = hydraulicsupportDao.queryFlicker(parram);
                        if (topList4.size() > 0) {
                            //记录为一次闪烁
                            t_2 = (long) topList4.get(0).get("datetime");
                        }
                    }
                }

            }
            if (t_1 > 0 && t_2 > 0) {
                I = EigenvalueAlgorithm.divide(1, t_2 - t_1, 0);
                Map<String,Object> resultMap = new HashMap<String,Object>();
                resultMap.put("leftFlickerValue", I);
                resultMap.put("leftFlickerTime", I);
                resultMap.put("rightFlickerValue", I);
                resultMap.put("rightFlickerTime", I);
                resultMap.put("totalFlickerValue", I);
                resultMap.put("totalFlickerTime", I);
                resultMap.put("datetime", datetime);
                result.add(resultMap);
            }
        }
        return result;
    }*/
    @Override
    public Map<String, Object> comprehensiveWarning(String mineId, String startTime, String endTime)
            throws Throwable {
        Map<String, Object> resultMap = new HashMap<>();
        long startTimeTimestamp = DateUtils.fomatDateTime(startTime).getTime();
        long endTimeTimestamp = DateUtils.fomatDateTime(endTime).getTime();
        Map<String, Object> parram = new HashMap<String, Object>();
        parram.put("tableId", "HYDRAULICSUPPORTWARNINGSTUDY");
        //parram.put("pk", "\'" + mineId + ".:." + deviceId + "\'");
        List<Map<String, Object>> studyInfo = hydraulicsupportDao.queryHydraulicSupportWarningStudy(parram);

        double R1 = 0.0;
        for (Map<String, Object> map : studyInfo) {
            R1 = R1 + Double.parseDouble(map.get("R1").toString());
        }


        //double R2 = Double.parseDouble(studyInfo.get("R2").toString());
        //Map<String, Object> map = new HashMap<String, Object>();
        //map.put("R1", R1);//短预警
        //map.put("R2", R1 > R2 ? R1 : R2);//长预警
        resultMap.put("R", new BigDecimal(R1).divide(new BigDecimal(3), 2, BigDecimal.ROUND_UP));
        parram.put("tableId", mineId + "." + "HYDRAULICSUPPORTWARNING");
        parram.put("size", 1);
        List<Map<String, Object>> w = hydraulicsupportDao.queryWarning(parram);
        parram.put("startTime", "\'" + startTimeTimestamp + "\'");
        parram.put("endTime", "\'" + endTimeTimestamp + "\'");
        parram.remove("size");
        List<Map<String, Object>> wLists = hydraulicsupportDao.queryWarning(parram);
        for (int i = 0; i < wLists.size(); i++) {
            long timestamp = (long) wLists.get(i).get("datetime");
            Date dateTime = DateUtils.fomatDateTime(timestamp);
            wLists.get(i).put("datetime", DateUtils.getTime(dateTime));
        }
        resultMap.put("W", w.get(0).get("w"));
        resultMap.put("result", wLists);

        return resultMap;
    }

    /*@Override public Map<String, Object> comprehensiveWarning(String mineId, String startTime, String endTime)
        throws Throwable {
        String startRow = "";
        String endRow = "";

        startTime = DateUtils.getBeforeDayDate(-30, startTime, "yyyy-MM-dd HH:mm:ss");

        List<Map<String, Object>> conditions = new ArrayList<Map<String, Object>>();
        Map<String, Object> parram = new HashMap<String, Object>();
        parram.put("columnFamily", "warning");
        parram.put("columnId", "entId");
        parram.put("valueType", "String");
        parram.put("value", mineId);
        parram.put("symbol", "EQUAL");
        conditions.add(parram);
        parram = new HashMap<String, Object>();
        parram.put("columnFamily", "warning");
        parram.put("columnId", "datetime");
        parram.put("valueType", "Long");
        parram.put("value", DateUtils.fomatDateTime(startTime).getTime());
        parram.put("symbol", "GREATER_OR_EQUAL");
        conditions.add(parram);
        parram = new HashMap<String, Object>();
        parram.put("columnFamily", "warning");
        parram.put("columnId", "datetime");
        parram.put("valueType", "Long");
        parram.put("value", DateUtils.fomatDateTime(endTime).getTime());
        parram.put("symbol", "LESS_OR_EQUAL");
        conditions.add(parram);

        if (StringUtils.isNotBlank(startTime) && StringUtils.isBlank(startRow)) {
            endRow = String.valueOf(DateUtils.fomatDateTime(startTime).getTime());
        }
        if (StringUtils.isNotBlank(endTime)) {
            startRow = String.valueOf(DateUtils.fomatDateTime(endTime).getTime());
        }

        List<Map<String, Object>> result =
            HBaseDriver.queryData("CalWarningHydraulic", conditions, -1, 100000, this.warning, startRow, endRow);

        double sumWi = 0.0;
        double sumRi = 0.0;
        double maxR = 0.0;
        double maxW = 0.0;
        for (int i = 0; i < result.size(); i++) {
            sumWi += Double.parseDouble(result.get(i).get("w1").toString());
            sumRi += Double.parseDouble(result.get(i).get("fitness").toString());
            maxR = maxR > Double.parseDouble(result.get(i).get("fitness").toString()) ?
                maxR :
                Double.parseDouble(result.get(i).get("fitness").toString());
            maxW = maxW > Double.parseDouble(result.get(i).get("w1").toString()) ?
                maxW :
                Double.parseDouble(result.get(i).get("w1").toString());
        }
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("R", maxR);
        map.put("W", EigenvalueAlgorithm.divide(sumWi * maxR, sumRi * maxW, 0));
        map.put("result", result);
        return map;
    }*/


    /**
     * @Description: 查询微震实时数据
     * @Param: [mineId, startTimeTimestamp, endTimeTimestamp]
     * @return: java.util.List<java.util.Map < java.lang.String, java.lang.Object>>
     * @Author: ChengQi
     * @Date: 2019/4/1
     */
    private List<Map<String, Object>> queryRealMicroseism(String mineId, long startTimeTimestamp,
                                                          long endTimeTimestamp) {
        Map<String, Object> parram = new HashMap<String, Object>();
        parram.put("tableId", mineId + "." + "MicroseismRealTime");
        parram.put("entId", "\'" + mineId + "\'");
        parram.put("startTime", "\'" + startTimeTimestamp + "\'");
        parram.put("endTime", "\'" + endTimeTimestamp + "\'");
        return microseismDao.queryRealMicroseism(parram);
    }
}
